// 基于 axios 封装的请求模块
import axios from 'axios'
import store from '@/store'
import router from '@/router'
import { clearStorage } from '@/utils/storage'
import Notify from '@/ui/Notify'

// import { refreshTokenAPI } from '@/api/index'
// 新建一个新的axios实例
const instance = axios.create({
  // baseURL: 'http://geek.itheima.net' // 基地址
  baseURL: 'http://toutiao.itheima.net' // 基地址
})

// 导出自定义函数, 参数对象解构赋值

// 旭哥思考：可能以后我会换掉axios,发送的参数配置项不确定（优化思想-大量项目经验）
// 中间用统一名字接收，函数内如何使用，统一在这里处理
// 好处：逻辑顶面直接还用这5个名配置项传入，将来如果内部改变，不需要动逻辑页面代码
// 只需要在这接收后，在函数内自己做处理即可（方便将来请求库的切换
export default ({ url, method = 'GET', params, data, headers }) => {
  return instance({
    url: url,
    method: method,
    params: params,
    data: data,
    headers: headers
  })
}

// 以后换库, 只需要改这里, 逻辑页面不用动, 保证代码的复用性和独立性(高内聚低耦合)
//   return $.ajax({
//     url: url,
//     type: method,
//     data: data,
//     header: headers
//   })

// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  // 注入全局token
  const token = store.state.token
  if (token && config.headers.Authorization === undefined) { // 登录页面无需携带
    config.headers.Authorization = `Bearer ${store.state.token}`
  }
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response
}, async function (error) {
  // 对响应错误做点什么
  if (error.response.status === 401) {
    // token续签方式1
    clearStorage() // 清空本地存储token
    // router.replace('/login') // 跳转至登录页重新获取token
    // router.currentRoute相当于在vue文件内this.$route->当前路由对象信息
    // fu11Path,路由对象里完整路由路径#后面的一切
    router.push({ path: `/login?path=${router.currentRoute.fullPath}` })
    // token续签方式2: refreshToken(用户无感知)

    // store.commit('setToken', '')
    // const res = await refreshTokenAPI()
    // // 新的token回来之后，我们要做什么
    // // 1.更新token在本地
    // store.commit('setToken', res.data.data.token)
    // // 2.更新新的token在请求头里
    // error.config.headers.Authorization = `Bearer ${res.data.data.token}`
    // // 3.未完成这次请求，再一次发起
    // // error.config就是上一次请求的配置对象
    // // 结果我们要return回原本逻辑页面调用地方-还是return回去一个Promise对象
    // return instance(error.config)
  } else if (error.response.status === 500 && error.config.url === '/v1_0/authorizations' && error.config.method === 'put') {
    // 刷新的refresh_token也过期了
    clearStorage() // 清除localStorage里所有值
    // localStorage当前网页, 域名划分, 每个域名下有自己范围的localStorage
    Notify({ type: 'warning', message: '身份已过期' })
    router.replace('/login')
  }
  return Promise.reject(error)
})

// 目标: token讲解
// 操作:
// 1. 手动修改localStorage里geek那个token改错(模拟过期)
// 2. 点击反馈/其他需要标明身份的接口(错误token携带给后台请求)
// 3. 反馈不感兴趣, 这次请求返回状态为 401, 进入错误响应拦截器

// 代码解决401问题
// 方式1: 清除token, 强制跳转回登录页面, 有感知重新登录, 拿到新token替换到本地
// 需要重新点击反馈按钮, 再次反馈 -> 感觉特别不好
// 方式2: 刷新token, 使用登录时保存的refresh_token, 调用另外一个接口, 换回来
// 新的token值, 替换到本地, 再次完成本次未完成的请求 -> 用户无感知体验好
// 1. 登录页面, localStorage.setItem('refresh_token', 存入refresh_token)
// 2. 401中, 注释掉跳转login的代码, 引入刷新token的api方法调用
// 3. 替换保存到本地新的token
// 4. error错误对象里headers替换成新的token
// 5. axios再次发起这次未完成请求, 返回Promise对象到最开始发请求的逻辑页面
// 注意: 调用刷新token的接口, 如果没携带refresh_token或者携带错误的都会导致500

// 401+500
// token和refresh_token都过期了 (前提, 是你手动把2个token改成错误的)
// 强制回到登录页
